package main

import "fmt"

func main() {
	/*
		1、slice := arr[start:end]
			切片中的数据：[start,end]
			arr[:end]：从头添加到 end
			arr[start:]：从 start 添加到末尾

		需要满足：0 <= start <= end <= cap(a)

		2、从已有的数组上，直接创建切片，该切片的底层数组就是当前的数组。
			长度是从 start 到 end 切割的数据量
			但是容量从 start 到数组的末尾

		3、基于字符串创建的切片和原字符串指向相同的底层字符数组，对字符串的切片操作返回的子串仍然是 string，而不是 slice

		4、append()函数，如果追加一个另一个切片在该切片的末尾，则应该在后面再加上“...”
			s1 = append(s1,s2...)
			不能追加一个数组给切片，必须转换成slice类型
		5.完整切片表达式：
			对于数组，指向数组的指针，或切片 a（注意不能是字符串）支持完整切片表达式：
				a[low : high : max]
			上述代码会构造与简单切片表达式 a[low : high] 相同类型、相同长度 和 元素的切片。
			另外，它会将得到的结果切片的容量设置为 max-low。
			在完整切片表达式中，只有 第一个 索引值 可以省略；它默认为 0。

		需要满足：0 <= low <= high <= max <= cap(t)
			可以手动控制新的切片的容量（在可行范围内）

	*/
	a := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	fmt.Println("--------------1.已有数组直接创建切片---------------")
	s1 := a[:5]            //0 ~ 4
	s2 := a[3:8]           //3 ~ 7
	s3 := a[5:]            //5 ~ (len(a)-1)
	s4 := a[:]             //0 ~ (len(a)-1)
	fmt.Println("a:", a)   //a: [1 2 3 4 5 6 7 8 9 10]
	fmt.Println("s1:", s1) //s1: [1 2 3 4 5]
	fmt.Println("s2:", s2) //s2: [4 5 6 7 8]
	fmt.Println("s3:", s3) //s3: [6 7 8 9 10]
	fmt.Println("s4:", s4) //s4: [1 2 3 4 5 6 7 8 9 10]

	fmt.Printf("%p\n", &a) //0xc000128050
	fmt.Printf("%p\n", s1) //0xc000128050

	fmt.Println("--------------2.长度和容量---------------")
	fmt.Printf("s1   len:%d,cap:%d\n", len(s1), cap(s1)) //s1   len:5,cap:10
	fmt.Printf("s2   len:%d,cap:%d\n", len(s2), cap(s2)) //s2   len:5,cap:7
	fmt.Printf("s3   len:%d,cap:%d\n", len(s3), cap(s3)) //s3   len:5,cap:5
	fmt.Printf("s4   len:%d,cap:%d\n", len(s4), cap(s4)) //s4   len:10,cap:10

	fmt.Println("--------------3.更改底层数组内容---------------")
	a[4] = 100
	fmt.Println(a)  //[1 2 3 4 100 6 7 8 9 10]
	fmt.Println(s1) //[1 2 3 4 100]
	fmt.Println(s2) //[4 100 6 7 8]
	fmt.Println(s3) //[6 7 8 9 10]
	fmt.Println(s4) //[1 2 3 4 100 6 7 8 9 10]

	fmt.Println("--------------3.更改切片内容---------------")
	s1[3] = 500
	fmt.Println(a)  //a   [1 2 3 500 100 6 7 8 9 10]
	fmt.Println(s1) //s1   [1 2 3 500 100]
	fmt.Println(s2) //s2   [500 100 6 7 8]
	fmt.Println(s3) //s3   [6 7 8 9 10]
	fmt.Println(s4) //s4   [1 2 3 500 100 6 7 8 9 10]

	fmt.Println("--------------4.向切片中添加元素（未超过数组容量）---------------")
	s1 = append(s1, 2, 3) // 原来在数组中的对应位置的数值被替换
	fmt.Println(a)        //a   [1 2 3 500 100 2 3 8 9 10]
	fmt.Println(s1)       //s1   [1 2 3 500 100 2 3 8 9 10]

	fmt.Println("--------------5.向切片中添加元素（超过了数组容量）---------------")
	s1 = append(s1, s4...) // 切片会指向一个新的底层数组,容量也变为原来的两倍
	fmt.Println(a)         //a   [1 2 3 500 100 2 3 8 9 10]
	fmt.Println(s1)        //s1   [1 2 3 500 100 2 3 1 2 3 500 100 2 3 8 9 10]

	fmt.Printf("a   len:%d,cap:%d\n", len(a), cap(a))    //a   len:10,cap:10
	fmt.Printf("s1   len:%d,cap:%d\n", len(s1), cap(s1)) //s1   len:17,cap:20

	fmt.Printf("s2   len: %d,cap:%d\n", len(s2), cap(s2)) //s2   len: 5,cap:7
	s2 = append(s2, s3...)
	fmt.Println(a)  //[1 2 3 500 100 2 3 8 9 10]
	fmt.Println(s2) //[500 100 2 3 8 2 3 8 9 10]

	fmt.Printf("a   len:%d,cap:%d\n", len(a), cap(a))    //a   len:10,cap:10
	fmt.Printf("s2   len:%d,cap:%d\n", len(s2), cap(s2)) //s2   len:10,cap:14

	fmt.Println("--------------6.完整切片表达式---------------------------")
	a1 := [5]int{1, 2, 3, 4, 5}
	t := a1[1:3:3]
	fmt.Printf("t:%v len(t):%v cap(t):%v\n", t, len(t), cap(t)) //t:[2 3] len(t):2 cap(t):2
}
